#include "KDJ_chart.h"
#include <vector>
#include <algorithm>
#include <map>
#include <iostream>
#include <limits>
#include "mouse_pos.h"

struct KDJData {
    double K;
    double D;
    double J;
};
std::vector<double> kValues, dValues, jValues;
// 静态存储K线数据
static std::vector<StockData> kLineData;
// 起止时间:
std::string currentStartDate,currentEndDate;

double calculateRSV(const std::vector<StockData>& stockData, int period, int index) {
    double minLow = std::numeric_limits<double>::max();
    double maxHigh = std::numeric_limits<double>::lowest();
    for (size_t i = index - period; i < index; ++i) {
        minLow = std::min(minLow, static_cast<double>(stockData[i].low));
        maxHigh = std::max(maxHigh, static_cast<double>(stockData[i].high));
    }
    double close = stockData[index].close;
    return (close - minLow) / (maxHigh - minLow) * 100;
}

void calculateKDJ(const std::vector<StockData>& stockData, int period, std::vector<KDJData>& kdjData) {
    std::vector<double> rsv;
    for (size_t i = period - 1; i < stockData.size(); ++i) {
        rsv.push_back(calculateRSV(stockData, period,i));
    }
    // 补空, 以能做到下标一致
    for(size_t i=0;i<period - 1;++i)
    {
        kdjData.push_back({0,0,0});
    }

    double k = 50.0, d = 50.0;
    for (size_t i = 0; i < rsv.size(); ++i) {
        k = (2.0 / 3.0) * k + (1.0 / 3.0) * rsv[i];
        d = (2.0 / 3.0) * d + (1.0 / 3.0) * k;
        double j = 3.0 * k - 2.0 * d;
        kdjData.push_back({k, d, j});
    }
}

void init_2(const std::vector<KDJData>& kdjData) {
    for (const auto& data : kdjData) {
        kValues.push_back(data.K);
        dValues.push_back(data.D);
        jValues.push_back(data.J);
    }
}

// 日期对应的下标
std::map<std::string,size_t> dateRangeMap;

void setKDJChartData(const std::vector<StockData>& stockData) {
    std::vector<KDJData> kdjData;
    calculateKDJ(stockData, 9, kdjData);
    init_2(kdjData);
    kLineData = stockData;
    for(size_t i=0;i<kLineData.size();i++)
    {
        dateRangeMap[kLineData[i].trade_date] = i;
    }
}

void setDateRangeForKDJ(const std::string& startDate, const std::string& endDate)
{
    if (startDate.empty() || endDate.empty()) {
        return;
    }
    currentStartDate = startDate;
    currentEndDate = endDate;
}

void drawLine(ImDrawList* drawList, const std::vector<double>& data, ImVec2 pos, ImVec2 size, 
    float minPrice, float maxPrice, ImU32 color) {
    if (data.empty()) return;
    // END 防范

    // BEGIN 起止下标
    // 取下标:
    // auto it_start = dateRangeMap.end();
    // it_start =dateRangeMap.lower_bound(currentStartDate);
    auto it_end = dateRangeMap.end();
    it_end = dateRangeMap.lower_bound(currentEndDate);
    size_t endIndex =0;
    if(it_end == dateRangeMap.end())
    {
        endIndex = dateRangeMap.size()-1;
    }
    else
    {
        // size_t startIndex = it_start->second;
        endIndex = it_end->second;
        if(!dateRangeMap.contains(currentEndDate)&&0!=endIndex)
        {
            --endIndex;
        }
    }
    // END 起止下标

    const size_t range = 90;
    //endIndex-startIndex+1;
    size_t startIndex=endIndex-90+1;
    if(0>int(endIndex)-90+1)
    {
        startIndex=0;
    }
    float step = size.x / range;
    float half_step = step*.5;
    for (size_t i = startIndex; i <= endIndex; ++i) {
        if (data[i] == 0.0f) continue;  // 跳过无效数据
        float x = pos.x + (i-startIndex) * step + half_step;
        float y = pos.y + (maxPrice - data[i]) * size.y / (maxPrice - minPrice);
        if (i == 0) {
            drawList->AddLine(ImVec2(x, y), ImVec2(x, y), color);
        } else {
            float prevX = pos.x + (i - 1 - startIndex) * step + half_step;
            float prevY = pos.y + (maxPrice - data[i - 1]) * size.y / (maxPrice - minPrice);
            drawList->AddLine(ImVec2(prevX, prevY), ImVec2(x, y), color);
        }
    }

}

// 绘制图表
void drawKDJLine(ImDrawList* drawList, ImVec2 pos, ImVec2 size)
{
    if (kLineData.empty()) {
        return;
    }
    if (kValues.empty() || dValues.empty() || jValues.empty()) {
        return;
    }
    if (currentStartDate.empty() || currentEndDate.empty()) {
        return;
    }

    // BEGIN 取最大值和最小值
    float maxValue=std::numeric_limits<float>::lowest(),minValue=0;
    // BEGIN 起止下标
    // 取下标:
    auto it_start = dateRangeMap.lower_bound(currentStartDate);
    auto it_end = dateRangeMap.lower_bound(currentEndDate);
    if(!dateRangeMap.contains(currentEndDate))
    {
        --it_end;
    }
    size_t startIndex = it_start->second;
    size_t endIndex = it_end->second;

    // END 起止下标
    for (size_t i = startIndex; i <= endIndex&& i<jValues.size(); ++i) {
        float currentValue = jValues[i];
        if (currentValue > maxValue) {
            maxValue = currentValue;
        } else if (currentValue < minValue) {
            minValue = currentValue;
        }
        currentValue = dValues[i];
        if (currentValue > maxValue) {
            maxValue = currentValue;
        } else if (currentValue < minValue) {
            minValue = currentValue;
        }
    }
    // END 取最大值和最小值

    drawLine(drawList,kValues , pos, size,minValue-2,maxValue+2,ImColor(0, 0, 255));
    drawLine(drawList,dValues , pos, size,minValue-2,maxValue+2,ImColor(0, 255, 0));
    drawLine(drawList,jValues , pos, size,minValue-2,maxValue+2,ImColor(255, 0, 0));

    // drawList->AddLine(ImVec2(0, 0), ImVec2(800, 800), ImColor(111, 111, 111));
    // drawList->AddLine(ImVec2(400, 0), ImVec2(400, 800), ImColor(111, 111, 111));
    // drawList->AddLine(ImVec2(400, 0), ImVec2(0, 800), ImColor(111, 111, 111));

    // drawList->AddLine(ImVec2(00, 800), ImVec2(400, 800), ImColor(111, 111, 111));
    // drawList->AddLine(ImVec2(800, 800), ImVec2(400, 800), ImColor(111, 111, 111));

    // 绘制文字:
    char text_value_to_string[128];
    float k = kValues[endIndex], d = dValues[endIndex], j = jValues[endIndex];
    snprintf(text_value_to_string,128,"K:%.2f",k);
    drawList->AddText(ImVec2(pos.x, pos.y + 20), ImColor(0, 0, 255), text_value_to_string);
    snprintf(text_value_to_string,128,"D:%.2f",d);
    drawList->AddText(ImVec2(pos.x, pos.y + 40), ImColor(0, 255, 0), text_value_to_string);
    snprintf(text_value_to_string,128,"J:%.2f",j);
    drawList->AddText(ImVec2(pos.x, pos.y + 60), ImColor(255, 0, 0), text_value_to_string);
    float k_d = kValues[endIndex]-dValues[endIndex];
    float prev_k_d = kValues[endIndex-1]-dValues[endIndex-1];
    snprintf(text_value_to_string,128,"k-d:%.2f",k_d);
    drawList->AddText(ImVec2(pos.x, pos.y + 80), ImColor(255, 255, 0), text_value_to_string);
    snprintf(text_value_to_string,128,"prev k-d:%.2f",prev_k_d);
    drawList->AddText(ImVec2(pos.x, pos.y + 100), ImColor(255, 255, 0), text_value_to_string);
    // 超买超卖:
    if(k>90&&d>80&&j>100)
    {
        drawList->AddText(ImVec2(pos.x+40, pos.y), ImColor(200, 0, 0), "超买");
        if(prev_k_d>0&&k_d<0)
        {
            drawList->AddText(ImVec2(pos.x+80, pos.y), ImColor(0, 200, 200), "死叉");
        }
    }
    else if(k<10&&d<20&&j<0)
    {
        drawList->AddText(ImVec2(pos.x+40, pos.y), ImColor(0, 200, 0), "超卖");
        if(k_d>0&&prev_k_d<0)
        {
            drawList->AddText(ImVec2(pos.x+80, pos.y), ImColor(200, 200, 0), "金叉");
        }
    }
    else if(k_d>0&&prev_k_d<0)
    {
        drawList->AddText(ImVec2(pos.x+80, pos.y), ImColor(100, 100, 100), "普通叉");
    }
    // 鼠标坐标:
    int mousePosX = getMousePosX();
    int mousePosY = getMousePosY();
    drawList->AddLine(ImVec2(mousePosX-9990, mousePosY), ImVec2(mousePosX+9990, mousePosY), ImColor(111, 111, 111));
    drawList->AddLine(ImVec2(mousePosX,mousePosY -9999), ImVec2(mousePosX,mousePosY +9999), ImColor(111, 111, 111));
}



// 普通叉
KDJ_API bool isCross()
{
    // 取下标:
    auto it_end = dateRangeMap.lower_bound(currentEndDate);
    if(dateRangeMap.end()==it_end)return false;
    if(!dateRangeMap.contains(currentEndDate))
    {
        --it_end;
    }
    size_t endIndex = it_end->second;

    float k = kValues[endIndex], d = dValues[endIndex], j = jValues[endIndex];    
    float k_d = kValues[endIndex]-dValues[endIndex];
    float prev_k_d = kValues[endIndex-1]-dValues[endIndex-1];
    
    return (k_d>0&&prev_k_d<0);
}

// 金叉
KDJ_API bool isGoldenCross()
{
    // 取下标:
    auto it_end = dateRangeMap.lower_bound(currentEndDate);
    if(dateRangeMap.end()==it_end)return false;
    if(!dateRangeMap.contains(currentEndDate))
    {
        --it_end;
    }
    size_t endIndex = it_end->second;
    
    float k = kValues[endIndex], d = dValues[endIndex], j = jValues[endIndex];    
    float k_d = kValues[endIndex]-dValues[endIndex];
    float prev_k_d = kValues[endIndex-1]-dValues[endIndex-1];

    if(k<10&&d<20&&j<0)
    {
        return (k_d>0&&prev_k_d<0);
    }
    return false;

}
